/**
 * poll函数测试；  也可以用一个数组来维护，进行优化；
 * @author: sundx
 * @date: 2020-05-31 21:44:15
 * @Last Modified by: sundx
 * @Last Modified time: 2020-06-08 00:32:55
 */

#include "wrap.h"
#include <cstring>
#include <iostream>
#include <poll.h>
#define POLL_OPEN_MAX 5000

int main() {
  struct sockaddr_in clientAddr;
  socklen_t addrLen = sizeof(clientAddr);
  struct pollfd allFd[POLL_OPEN_MAX]; //建立一个数组；
  int listenFd = sdx::serverSocketBindListen();
  allFd[0].fd = listenFd;
  allFd[0].events = POLLIN;
  allFd[0].revents = 0;
  for (int i = 1; i < POLL_OPEN_MAX; ++i) {
    allFd[i].fd = -1;
  }
  int maxFdNum = 1;
  while (1) {
    //传入数组地址，一共检测的Fd的总数，设置阻塞；
    int activeFd = poll(allFd, maxFdNum, -1);
    if (activeFd == -1) {
      sdx::printError("poll error...");
    }
    if (allFd[0].revents & POLLIN) { //如果是监听事件；
      int cnnFd = accept(listenFd, (sockaddr *)&clientAddr, &addrLen);
      char clientAddrChar[INET_ADDRSTRLEN];
      std::cout << inet_ntop(AF_INET, &clientAddr.sin_addr, clientAddrChar,
                             INET_ADDRSTRLEN)
                << " " << ntohs(clientAddr.sin_port) << std::endl;
      int i;
      for (i = 1; i < POLL_OPEN_MAX; ++i) { //找到最小的那个可用空位；
        if (allFd[i].fd < 0) {
          allFd[i].fd = cnnFd;
          allFd[i].events = POLLIN;
          allFd[i].revents = 0;
          ++maxFdNum;
          break;
        }
      }
      if (i == POLL_OPEN_MAX) { //满了
        sdx::printError("too many clients...");
      }
      if (--activeFd == 0) //如果只有一个监听事件，直接进入下一次poll阻塞等待；
        continue;
    }
    for (int index = 1; index < POLL_OPEN_MAX; ++index) { //定位通信fd
      int cnnFd = allFd[index].fd;
      if (cnnFd < 0)
        continue; //如果是-1，则跳过
      if (allFd[index].revents & POLLIN) {
        char inbuff[MESSAGE_SIZE];   //读缓冲区
        bzero(inbuff, MESSAGE_SIZE); //初始化缓冲区
        int recvBytes = recv(cnnFd, inbuff, MESSAGE_SIZE, 0);
        if (recvBytes == 0) { //判断是否是客户端关闭
          std::cout << " close the connect..." << std::endl;
          close(cnnFd);
          allFd[index].fd = -1; //设为初始状态；
          --maxFdNum;           //减去关心的文件描述符总数
        } else if (recvBytes > 0) {
          std::cout << "receive " << recvBytes << " bytes message from "
                    << ", and the message is " << inbuff << std::endl;

          for (int j = 0; j < recvBytes; ++j) { // 小写转大写
            inbuff[j] = toupper(inbuff[j]);
          }

          int ret = send(cnnFd, inbuff, recvBytes, 0); //发送
          if (ret == -1) {
            sdx::printError("recv failed");
          }
          //判断当前是否为最后一个激活的Fd，如果是则跳出循坏；
          if (--activeFd == 0)
            break;
        } else { //判断是否出错；
          if ((errno == ECONNABORTED) || (errno == EINTR)) {
            continue;
          } else {
            sdx::printError("recv error...");
          }
        }
      }
    }
  }
  return 0;
}